
//  HybridBaseHandler.swift
//  MeenoHybrid
//
//  Created by alyadan on 2016/10/15.
//  Copyright © 2016年 alyadan. All rights reserved.
//

import Foundation
import YD_Util
import RxSwift


open class HybridBaseHandler: NSObject, HybridHandlerProtocol {
    
//#define MNWEB_ERROR_OK  0
//#define MNWEB_ERROR_PARAM  1
//#define MNWEB_ERROR_METHOD_NOT_FOUND  2
//#define MNWEB_ERROR_PLUGIN  10  // 表示Plugin内部错误
    
    public let disposeBag = DisposeBag()
    
    public var bridge: WebViewJavascriptBridge? {
       return (self.hybridWebViewModel as? HybridWebViewModel)?.bridge
    }
    
    deinit {
        print("-------deinit handler\(self)");
    }
    
    
    public  static let emptyData = [String: Any]()
    
    
    public var name = "HybridBaseHandler"
    
    weak public var hybridVCModel: HybridBaseVCModel?
    weak public var hybridWebViewModel: HybridBaseWebViewModel?
    
    
    public static func callH5Method(hybridWebViewModel: HybridBaseWebViewModel , methodName:String, param: MeenoHybrid.DictType){
        
        (hybridWebViewModel as? HybridWebViewModel)?.bridge?.send(HybridBaseHandler.createSendData(method: methodName, data: param))
    }
    
    
    public func register(bridge: WebViewJavascriptBridgeProtocol, webViewModel: HybridBaseWebViewModel) {
        self.hybridVCModel = webViewModel.getHybridVCModel()
        self.hybridWebViewModel = webViewModel
        
        bridge.registerHandler(handlerName: name) { (data:Any?, responseCallback:WVJBResponseCallback?) in
            do{
                
                try self.deal(data: data, responseCallback: responseCallback!)
                
            }catch HybridError.dataParamError{
                
                self.callbackParamError(callback: responseCallback)
                
            }catch HybridError.methodError{
                
                self.callbackMethodError(callback: responseCallback)
            
            }catch HybridError.pluginError{
                
                self.callbackFail(callback: responseCallback, error: 10, subError: 0, errMsg: "plugin error")
                
            }catch{
                
                print(error)
            }
        }
        
    }
    
    
    public static func createSendData(method: String, data: [String: Any] = [:]) -> [String: Any]{
        return [
            "method": method,
            "data": data
        ]
    }
    
    
    internal func reciveErrorData(data: MeenoHybrid.DictType) {
       print("recive Error Data from js \(data)")
    }
    
    //MARK: internal
    
    /// 解决 闭包无法通过 perform 传递
   public class BlockWarp:NSObject {
        
       public private(set) var  task:WVJBResponseCallback?
        
        init(task:WVJBResponseCallback?) {
            self.task = task
            super.init()
        }
        
    }
    
    
   public enum HybridError:Int, Error {
        case dataParamError = 1
        case methodError = 2
        case pluginError = 10
    }
    
    func deal(data:Any? , responseCallback:@escaping WVJBResponseCallback) throws{
        
        // NSLog(@"OC data: %@", data);
        /*
         var data =
         {
	         "method" : "urlRequest",
	         "data" : {
			         "path" : path,
			         "params" : ""
			         }
         }
         */
        
        
        guard let jsonStrin = data as? String else {
            
            throw HybridError.dataParamError
        }
        
        let data = try jsonStrin.ParseJSONString()
        
        guard let responseData = data as? [String : Any] else{
            
            throw HybridError.dataParamError
        }
        
        guard let method = responseData["method"] as? String ,let receiveData = responseData["data"] else {
            throw HybridError.dataParamError
        }
        
        
        let sel = NSSelectorFromString(method + "WithData:callback:")
        
//        let str = NSStringFromSelector(#selector(MNAppHandler.openViewController(data:callback:)))
//        print(str, method + "WithData:callback:")
        
        guard self.responds(to: sel) == true else {
            throw HybridError.methodError
        }
        
        let blockWarp = BlockWarp(task:responseCallback)
        
        self.perform(sel, with:receiveData, with: blockWarp)
    }
    
    
    public func callbackParamError(callback: WVJBResponseCallback?){
       callbackFail(callback: callback, error: 1, subError: 0, errMsg: "param error")
    }
    
    public func callbackMethodError(callback: WVJBResponseCallback?){
       callbackFail(callback: callback, error: 2, subError: 0, errMsg: "method not found")
    }
    
    public func callbackPluginError(callback: WVJBResponseCallback?){
       callbackFail(callback: callback, error: 10, subError: 0, errMsg: "plugin error")
    }
    
    public func callbackFail(callback: WVJBResponseCallback?, error:Int, subError:Int, errMsg: String) {
        
        let retDict: MeenoHybrid.DictType = [
            "error" : error,
            "subError" : subError,
            "errMsg" : errMsg,
            "data" : HybridBaseHandler.emptyData
        ]
        
        guard let jsonRet = try? String.JSONSerializ(withObject: retDict),let responseCallback = callback else {
            print("json serializ failed")
            return
        }
        
        
        print("callback failed with data:\(retDict)")
        responseCallback(jsonRet)
        
    }
    
    
    public func callbackSuccess(callback: WVJBResponseCallback?, data:MeenoHybrid.DictType?) {
        
        let retDict: MeenoHybrid.DictType = [
            "error" : 0,
            "subError" : 0,
            "errMsg" : "",
            "data" : data ?? HybridBaseHandler.emptyData
        ]
        
        guard let jsonRet = try? String.JSONSerializ(withObject: retDict) else {
            print("json serializ failed")
            return
        }
        
        
        callback?(jsonRet)
        
    }
    
}
